home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac 1993 September / clonecd / September 93.img / Archives / Applications / Assorted Programs / PCB Cad / PCBPRINT.C < prev    next >
C/C++ Source or Header  |  1990-10-10  |  12KB  |  419 lines

  1. /*
  2. ** printed circuit board printer, Copyright (C) Randy Nevin 1989.
  3. **
  4. ** you may give this software to anyone, make as many copies as you like, and
  5. ** post it on public computer bulletin boards and file servers. you may not
  6. ** sell it or charge any fee for distribution (except for media and postage),
  7. ** remove this comment or the copyright notice from the code, or claim that
  8. ** you wrote this code or anything derived from it. you may modify the code as
  9. ** much as you want (please document clearly with comments, and maintain the
  10. ** coding style), but programs which are derived from this one are subject to
  11. ** the conditions stated here. i am providing this code so that people can
  12. ** learn from it, so if you distribute it, please include source code, not
  13. ** just executables. contact me to report bugs or suggest enhancements; i do
  14. ** not guarantee support, but i will make an effort in good faith to help you,
  15. ** and i want to act as a central clearing house for future versions. you
  16. ** should contact me before undertaking a significant development effort, to
  17. ** avoid reinventing the wheel. if you come up with an enhancement you
  18. ** consider particularly useful, i would appreciate being informed so that it
  19. ** can be incorporated in future versions. my address is: Randy Nevin,
  20. ** 1731 211th PL NE, Redmond, WA 98053. this code is available directly from
  21. ** the author; just send a floppy and a self-addressed floppy mailer with
  22. ** sufficient postage.
  23. **
  24. ** HISTORY
  25. ** (name        date        description)
  26. ** ----------------------------------------------------
  27. ** randy nevin        3/4/89        initial version
  28. ** randy nevin        3/4/89        released version 1.00
  29. */
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include "cell.h"
  35.  
  36. #ifdef THINK_C
  37. #include <console.h>
  38. #endif
  39.  
  40.  
  41. /*
  42. ** usage: PCBPRINT [/P] [/L] [/Rn] [/Zm] infile
  43. **
  44. ** /P indicates portrait orientation (paper is longer from top to bottom), and
  45. ** /L indicates landscape orientation (paper is longer side-to-side). only one
  46. ** of /P and /L can be present. n is the laser printer resolution (75, 100,
  47. ** 150, or 300) and m is the zoom factor (0, 1, 2, or 3 ). the defaults are:
  48. ** /P /R150 /Z1. this program creates 6 output files (H, T, B, HT, HB, and
  49. ** HTB). each of these files can be fed to a hewlett-packard laser printer to
  50. ** produce a picture of part or all of the routed printed circuit board. H
  51. ** contains commands to print only the holes and routing holes. T and B
  52. ** contain commands to print only the top-side or bottom-side traces,
  53. ** respectively. HT and HB are the same, but also include the holes, and HTB
  54. ** contains everything (holes, top-side traces, and bottom-side traces).
  55. */
  56.  
  57. #define MAXZOOM    3    /* maximum zoom number; minimum is 0 */
  58.  
  59. #define ZOOM0    3    /* 3x3 dots per cell    */
  60. #define ZOOM1    6    /* 6x6 dots per cell    */
  61. #define ZOOM2    10    /* 10x10 dots per cell    */
  62. #define ZOOM3    18    /* 18x18 dots per cell    */
  63.  
  64. static int size[MAXZOOM+1] = { ZOOM0, ZOOM1, ZOOM2, ZOOM3 };
  65.  
  66. #define H    1    /* holes                */
  67. #define T    2    /* top-side traces            */
  68. #define B    4    /* bottom-side traces            */
  69. #define HT    (H+T)    /* holes and top-side traces        */
  70. #define HB    (H+B)    /* holes and bottom-side traces        */
  71. #define HTB    (H+T+B)    /* holes, top- and bottom-side traces    */
  72.  
  73. static int currnt;    /* current image type (one of the six above)    */
  74. static int orient;    /* 0=portrait, 1=landscape            */
  75. static int resol;    /* resolution (one of 75,100,150,300)        */
  76. static int zoom;    /* 0=3x3, 1=6x6, 2=10x10, 3=18x18        */
  77. static int nbytes;    /* number of bytes per image row        */
  78.  
  79. int justboard = 1; /* only need the board data structure */
  80.  
  81. /* board dimensions */
  82. extern int Nrows;
  83. extern int Ncols;
  84.  
  85. extern void InitBoard( void );
  86. extern long GetCell( int, int, int );
  87. extern void SetCell( int, int, int, long );
  88.  
  89. void main( int, char *[] );
  90. static void dofile( char *, int );
  91. static void prolog( FILE * );
  92. static void epilog( FILE * );
  93. static void doimage( FILE * );
  94. static void map( long, long, int, FILE * );
  95. static void initbit( void );
  96. static void flushbit( FILE * );
  97. static void outbit( int, FILE * );
  98.  
  99. void main ( argc, argv ) /* input routed board, output laser printer files */
  100.     int argc;
  101.     char *argv[];
  102.     {
  103.     char *self, *p;
  104.     register int r, c;
  105.     int i1, i2, i3, i4, i, j;
  106.     FILE *fp;
  107.     long x;
  108.     char oset, rset, zset;
  109.  
  110. #ifdef THINK_C
  111.     argc = ccommand (&argv);        /* simulate command-line arguments */
  112. #endif
  113.  
  114.  
  115.     printf( "Copyright (C) Randy Nevin, 1989. Version 1.00\n" );
  116.     printf( "See source code for rights granted.\n\n" );
  117.     orient = 0; /* portrait mode */
  118.     resol = 150; /* 150 dots per inch */
  119.     zoom = 1; /* 6x6 cells */
  120.     oset = rset = zset = 0; /* so far, just defaults */
  121.     self = argv[0];
  122.     /* get rid of initial part of path */
  123.     if ((p = strrchr( self, '\\' )) || (p = strrchr( self, ':' )))
  124.         self = ++p;
  125.     if (argc < 2 || argc > 5) { /* need infile and up to 4 switches */
  126.         fprintf( stderr, "usage: %s [/P] [/L] [/Rn] [/Zm] infile\n",
  127.             self );
  128.         fprintf( stderr, " P = portrait orientation\n" );
  129.         fprintf( stderr, " L = landscape orientation\n" );
  130.         fprintf( stderr, " n = resolution (75,100,150,300)\n" );
  131.         fprintf( stderr, " m = zoom (0,1,2,3)\n" );
  132.         exit( -1 );
  133.         }
  134.     for (i = 1; i < argc-1; i++) { /* process switches */
  135.         if (*argv[i] == '/' && (*(argv[i]+1) == 'P'
  136.             || *(argv[i]+1) == 'p') && *(argv[i]+2) == 0) {
  137.             if (oset)
  138.                 fprintf( stderr, "duplicate orientation %s\n",
  139.                     argv[i] );
  140.             else {
  141.                 oset = 1;
  142.                 orient = 0;
  143.                 }
  144.             }
  145.         else if (*argv[i] == '/' && (*(argv[i]+1) == 'L'
  146.             || *(argv[i]+1) == 'l') && *(argv[i]+2) == 0) {
  147.             if (oset)
  148.                 fprintf( stderr, "duplicate orientation %s\n",
  149.                     argv[i] );
  150.             else {
  151.                 oset = 1;
  152.                 orient = 1;
  153.                 }
  154.             }
  155.         else if (*argv[i] == '/' && (*(argv[i]+1) == 'R'
  156.             || *(argv[i]+1) == 'r')) {
  157.             if (rset)
  158.                 fprintf( stderr, "duplicate resolution %s\n",
  159.                     argv[i] );
  160.             else {
  161.                 rset = 1;
  162.                 resol = atoi( argv[i]+2 );
  163.                 }
  164.             }
  165.         else if (*argv[i] == '/' && (*(argv[i]+1) == 'Z'
  166.             || *(argv[i]+1) == 'z')) {
  167.             if (zset)
  168.                 fprintf( stderr, "duplicate zoom %s\n",
  169.                     argv[i] );
  170.             else {
  171.                 zset = 1;
  172.                 zoom = atoi( argv[i]+2 );
  173.                 }
  174.             }
  175.         else
  176.             fprintf( stderr, "unknown option %s\n", argv[i] );
  177.         }
  178.     if (!(fp = fopen( argv[argc-1], "rb" ))) {
  179.         fprintf( stderr, "can't open %s\n", argv[argc-1] );
  180.         exit( -1 );
  181.         }
  182.     /* fetch the board dimensions */
  183.     if ((i = getc( fp )) == EOF || (j = getc( fp )) == EOF) {
  184.         fprintf( stderr, "premature eof\n" );
  185.         exit( -1 );
  186.         }
  187.     Nrows = (i & 0xFF) | ((j << 8) & 0xFF00);
  188.     if ((i = getc( fp )) == EOF || (j = getc( fp )) == EOF) {
  189.         fprintf( stderr, "premature eof\n" );
  190.         exit( -1 );
  191.         }
  192.     Ncols = (i & 0xFF) | ((j << 8) & 0xFF00);
  193.     InitBoard(); /* allocate memory for data structures */
  194.     for (r = 0; r < Nrows; r++) { /* read in the board, row by column */
  195.         for (c = 0; c < Ncols; c++) {
  196.             /* first do top-side */
  197.             if ((i1 = getc( fp )) == EOF
  198.                 || (i2 = getc( fp )) == EOF
  199.                 || (i3 = getc( fp )) == EOF
  200.                 || (i4 = getc( fp )) == EOF) {
  201.                 fprintf( stderr, "premature eof\n" );
  202.                 exit( -1 );
  203.                 }
  204.             x = (long)i1 | (((long)i2) << 8)
  205.                 | (((long)i3) << 16) | (((long)i4) << 24);
  206.             SetCell( r, c, TOP, x );
  207.             /* then do bottom-side */
  208.             if ((i1 = getc( fp )) == EOF
  209.                 || (i2 = getc( fp )) == EOF
  210.                 || (i3 = getc( fp )) == EOF
  211.                 || (i4 = getc( fp )) == EOF) {
  212.                 fprintf( stderr, "premature eof\n" );
  213.                 exit( -1 );
  214.                 }
  215.             x = (long)i1 | (((long)i2) << 8)
  216.                 | (((long)i3) << 16) | (((long)i4) << 24);
  217.             SetCell( r, c, BOTTOM, x );
  218.             }
  219.         }
  220.     nbytes = (Ncols * size[zoom] + 7) / 8;
  221.     dofile( "H",   H   );
  222.     dofile( "T",   T   );
  223.     dofile( "B",   B   );
  224.     dofile( "HT",  HT  );
  225.     dofile( "HB",  HB  );
  226.     dofile( "HTB", HTB );
  227.     exit( 0 );
  228.     }
  229.  
  230. static void dofile ( p, i ) /* create a board image file */
  231.     char *p;
  232.     int i;
  233.     {
  234.     FILE *fp;
  235.  
  236.     printf( "producing %s image file\n", p );
  237.     currnt = i;
  238.     if (!(fp = fopen( p, "wb" ))) {
  239.         fprintf( stderr, "can't open %s\n", p );
  240.         exit( -1 );
  241.         }
  242.     prolog( fp ); /* initial laser printer commands */    
  243.     doimage( fp ); /* create the board image */
  244.     epilog( fp ); /* final laser printer commands */
  245.     if (fclose( fp )) {
  246.         fprintf( stderr, "can't close %s\n", p );
  247.         exit( -1 );
  248.         }
  249.     }
  250.  
  251. static void prolog ( fp ) /* output initial laser printer commands */
  252.     register FILE *fp;
  253.     {
  254.     putc( 0x1B, fp );        /* <esc> */
  255.     putc( 'E', fp );        /* reset */
  256.     putc( 0x1B, fp );        /* <esc> */
  257.     fprintf( fp, "&l%dO", orient );    /* set image orientation */
  258.     putc( 0x1B, fp );        /* <esc> */
  259.     fprintf( fp, "&a10R" );        /* cursor to row 10 */
  260.     putc( 0x1B, fp );        /* <esc> */
  261.     fprintf( fp, "&a10C" );        /* cursor to column 10 */
  262.     putc( 0x1B, fp );        /* <esc> */
  263.     fprintf( fp, "*t%dR", resol );    /* set resolution in dots per inch */
  264.     putc( 0x1B, fp );        /* <esc> */
  265.     fprintf( fp, "*r1A" );        /* start graphics at cursor */
  266.     }
  267.  
  268. static void epilog ( fp ) /* output final laser printer commands */
  269.     register FILE *fp;
  270.     {
  271.     putc( 0x1B, fp );    /* <esc> */
  272.     fprintf( fp, "*rB" );    /* end graphics */
  273.     putc( 0x12, fp );    /* formfeed to eject paper */
  274.     putc( 0x1B, fp );    /* <esc> */
  275.     putc( 'E', fp );    /* reset */
  276.     }
  277.  
  278. static void doimage ( fp ) /* create the board image, row by column */
  279.     FILE *fp;
  280.     {
  281.     register int r, c;
  282.     int ir;
  283.     long x, y;
  284.  
  285.     for (r = Nrows-1; r >= 0; r--) { /* each row */
  286.         for (ir = size[zoom]-1; ir >= 0; ir--) { /* each scan line */
  287.             putc( 0x1B, fp );    /* <esc> */
  288.             fprintf( fp, "*b%dW", nbytes );
  289.             initbit();
  290.             for (c = 0; c < Ncols; c++) {
  291.                 x = GetCell( r, c, TOP );
  292.                 y = GetCell( r, c, BOTTOM );
  293.                 map( x, y, ir, fp );
  294.                 }
  295.             flushbit( fp );
  296.             }
  297.         }
  298.     }
  299.  
  300. struct x { /* group the bit templates for an object */
  301.     long t;            /* the object type    */
  302.     char t0[ZOOM0][ZOOM0];    /* tiny zoom template    */
  303.     char t1[ZOOM1][ZOOM1];    /* small zoom template    */
  304.     char t2[ZOOM2][ZOOM2];    /* medium zoom template    */
  305.     char t3[ZOOM3][ZOOM3];    /* large zoom template    */
  306.     };
  307.  
  308. extern struct x y1[];  /* hole templates        */
  309. extern struct x y2[];  /* hole-related templates    */
  310. extern struct x y3[];  /* non-hole-related templates    */
  311.  
  312. extern int z1;  /* number of hole types            */
  313. extern int z2;  /* number of hole-related types        */
  314. extern int z3;  /* number of non-hole-related types    */
  315.  
  316. #define domap1(v)    { int i; \
  317.               for (i = 0; i < z1; i++) { \
  318.                 if (v & (y1[i].t)) { \
  319.                     if (zoom == 0) \
  320.                         bit |= y1[i].t0[ir][ic]; \
  321.                     else if (zoom == 1) \
  322.                         bit |= y1[i].t1[ir][ic]; \
  323.                     else if (zoom == 2) \
  324.                         bit |= y1[i].t2[ir][ic]; \
  325.                     else if (zoom == 3) \
  326.                         bit |= y1[i].t3[ir][ic]; \
  327.                     } \
  328.                 if (bit) \
  329.                     break; \
  330.                 } }
  331.  
  332. #define domap2(v)    { int i; \
  333.               for (i = 0; i < z2; i++) { \
  334.                 if (v & (y2[i].t)) { \
  335.                     if (zoom == 0) \
  336.                         bit |= y2[i].t0[ir][ic]; \
  337.                     else if (zoom == 1) \
  338.                         bit |= y2[i].t1[ir][ic]; \
  339.                     else if (zoom == 2) \
  340.                         bit |= y2[i].t2[ir][ic]; \
  341.                     else if (zoom == 3) \
  342.                         bit |= y2[i].t3[ir][ic]; \
  343.                     } \
  344.                 if (bit) \
  345.                     break; \
  346.                 } }
  347.  
  348. #define domap3(v)    { int i; \
  349.               for (i = 0; i < z3; i++) { \
  350.                 if (v & (y3[i].t)) { \
  351.                     if (zoom == 0) \
  352.                         bit |= y3[i].t0[ir][ic]; \
  353.                     else if (zoom == 1) \
  354.                         bit |= y3[i].t1[ir][ic]; \
  355.                     else if (zoom == 2) \
  356.                         bit |= y3[i].t2[ir][ic]; \
  357.                     else if (zoom == 3) \
  358.                         bit |= y3[i].t3[ir][ic]; \
  359.                     } \
  360.                 if (bit) \
  361.                     break; \
  362.                 } }
  363.  
  364. static void map ( v0, v1, ir, fp ) /* map a cell to the image */
  365.     long v0, v1;
  366.     int ir;
  367.     FILE *fp;
  368.     {
  369.     register int ic, bit;
  370.  
  371.     for (ic = 0; ic < size[zoom]; ic++) { /* do each scan column */
  372.         bit = 0;
  373.         if (v0 & HOLE) {
  374.             if (currnt & H) /* plot holes? */
  375.                 domap1( v0 );
  376.             if (!bit && (currnt & T)) /* plot top-side? */
  377.                 domap2( v0 );
  378.             if (!bit && (currnt & B)) /* plot bottom-side? */
  379.                 domap2( v1 );
  380.             }
  381.         else {
  382.             if (v0 && (currnt & T)) /* plot top-side? */
  383.                 domap3( v0 );
  384.             if (!bit && v1 && (currnt & B)) /* plot bottom-side? */
  385.                 domap3( v1 );
  386.             }
  387.         outbit( bit, fp );
  388.         }
  389.     }
  390.  
  391. static int shift; /* how far to shift next bit */
  392. static char byte; /* the byte buffer */
  393.  
  394. static void initbit () { /* initialize bit output */
  395.     byte = 0;
  396.     shift = 7;
  397.     }
  398.  
  399. static void flushbit ( fp ) /* flush bit output */
  400.     FILE *fp;
  401.     {
  402.     if (shift != 7) /* buffer empty? */
  403.         putc( byte, fp ); /* no, output partial byte */
  404.     }
  405.  
  406. static void outbit( bit, fp ) /* output a bit using byte buffering */
  407.     int bit;
  408.     FILE *fp;
  409.     {
  410.     byte |= ((char)bit << shift);
  411.     if (!shift) {
  412.         putc( byte, fp );
  413.         byte = 0;
  414.         shift = 7;
  415.         }
  416.     else
  417.         shift--;
  418.     }
  419.